package com.UdpRecieve.tool.lisichen;


import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Date;

public class HttpUtils {
    private final static Logger logger = LoggerFactory.getLogger(HttpUtils.class);
    //访问WebService接口的路径 9898是WebService jar包中application.properties设置的端口号
    private final static String JAVA_URL= "http://192.168.1.244:9898";

    public static String sendPost(String url, JSONObject jsonObject) {
        try {
            logger.debug(jsonObject.toString());
            CloseableHttpClient client = null;
            CloseableHttpResponse response = null;
            try {
                ObjectMapper objectMapper = new ObjectMapper();

                HttpPost httpPost = new HttpPost(url);
                httpPost.setHeader(HTTP.CONTENT_TYPE, "application/json");
                httpPost.addHeader("USERNAME", "sysadmin");
                httpPost.addHeader("admflg", "1");
                httpPost.setEntity(new StringEntity(objectMapper.writeValueAsString(jsonObject),
                        ContentType.create("text/json", "UTF-8")));

                client = HttpClients.createDefault();
                response = client.execute(httpPost);
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity);
                logger.debug("=========", result);
                //System.out.println("========"+result);
                return result;
            } finally {
                if (response != null) {
                    response.close();
                }
                if (client != null) {
                    client.close();
                }
            }
        } catch (Exception e) {
            logger.error("http Post请求异常", e);
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 获取允许文件上传的大小，超过则分块上传
     *
     * @return
     */
    public static int adslGetBlockSize() {
        int retStr = -1;
        JSONObject jsonObj = new JSONObject();
        jsonObj.put("optType", -1);
        String str = sendPost(JAVA_URL + "/OptJavaFileSlab", jsonObj);
        JSONObject ret = JSONObject.parseObject(str);
        if (ret.getInteger("ret") == 1) {
            retStr = ret.getInteger("cont");
        }
        return retStr;
    }

    /**
     * 获取版本
     *
     * @return
     */
    public static String adslGetVersion() {
        String retStr = "";
        JSONObject jsonObj = new JSONObject();
        jsonObj.put("optType", 0);
        String str = sendPost(JAVA_URL + "/OptJavaFileSlab", jsonObj);
        JSONObject ret = JSONObject.parseObject(str);
        if (ret.getInteger("ret") == 1) {
            retStr = ret.getString("cont");
        } else {
            retStr = ret.getString("error");
        }
        return retStr;
    }


    public void setLogger(){
        File file1 = new File("E:\\mnt\\dcas\\logs\\sys-user.log");
        System.out.println(file1.getPath().replaceAll(file1.getName(),""));
    }
    /**加密
     * 加密
     * @param srcFile 明文文将
     * @param decFile 加密后保存的文件
     * @return
     */
    public static String adslAddSlabel(String srcFile, String decFile) {
        if(decFile.equals("")){
            decFile=srcFile;

            File file1 = new File(decFile);
            String fileDescP = file1.getPath().replaceAll(file1.getName(),"");
            File file2 = new File(fileDescP);
            if (!file2.exists()){
                file2.mkdirs();
            }
        }
        JSONObject docAttach = new JSONObject();
        JSONObject jsonObj = new JSONObject();
        jsonObj.put("optType", 1);
        String ok="";
        //明文文件
        File file = new File(srcFile);
        //密级文件
        int bigSize = adslGetBlockSize();
        if (file.length() > bigSize) {
            docAttach.put("bigFlag", true);
        }else{
            docAttach.put("bigFlag", false);
        }
        docAttach.put("FileName", file.getName());
        docAttach.put("Data", getFileData(file,bigSize));

        String xmlString = XmlUtils.createSercetXml();//密级属性字符串
        jsonObj.put("slInfo", new String(Base64.encodeBase64(xmlString.getBytes())));//密级设置

        jsonObj.put("docAttach", docAttach);
        String slabelStr=sendPost(JAVA_URL+"/OptJavaFileSlab",jsonObj);
        JSONObject ret= JSONObject.parseObject(slabelStr);
        if (ret.getInteger("ret") == 1 ) {
            long totalS=ret.getLong("totalS");//获取操作文件后文件的大小
            JSONObject docA= JSONObject.parseObject(ret.getString("slAttach"));
            String FileName=docA.getString("FileName");
            if(totalS>bigSize) {
                long readSize = 0;
                JSONObject json = new JSONObject();
                while (readSize < totalS) {
                    json = new JSONObject();
                    json.put("FileName",FileName);
                    json.put("readSize", readSize);
                    String bigStr = sendPost(JAVA_URL + "/BigFileDown", json);
                    JSONObject bigret = JSONObject.parseObject(bigStr);
                    readSize = bigret.getLong("readSize");
                    writeFile(decFile, bigret.getString("Data"));
                }
                ok=file_get_contents(decFile);
                System.out.println("大文件加密成功");
            }else {
                //writeFile(decFile, docA.getString("Data"));
                byte[] as = Base64.decodeBase64(docA.getString("Data").getBytes());
                ok=new String(as);
                //ok=new String(Base64.decodeBase64(docA.getString("Data").getBytes()),"UTF-8");//中文乱码时要抛异常
                writeByteArrayToFile(as,decFile);
                System.out.println("文件加密成功");
            }
        }else
            ok="0";
        return ok;
    }

    /**
     * 把byte数组写成文件
     * @param datas 文件的byte数组
     * @param destFileName 文件地址
     * @return
     */
    public static String writeByteArrayToFile(byte[] datas, String destFileName) {
        // 文件输出流（需要关闭）
        OutputStream os = null;
        try {
            // 字节数组输入流（不需要关闭）
            InputStream is = new ByteArrayInputStream(datas);
            os = new FileOutputStream(new File(destFileName));

            byte[] buf = new byte[1024];
            int len;
            while (((len = is.read(buf)) != -1)) {
                os.write(buf, 0, len);
            }
            os.flush();
            return "成功!";
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return "失败!";
        } catch (IOException e) {
            e.printStackTrace();
            return "失败!";
        } finally {
            if (os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 读取标志，读取加密文件的加密信息
     * @param srcFile 加密后的密文文件
     * @param decFile 读取密文文件的密级信息保存的文件
     * @return
     */
    public static String adslReadSlabelInfo(String srcFile,String decFile){
        if(decFile.equals("")){
            decFile=srcFile;
        }
        JSONObject docAttach = new JSONObject();
        JSONObject jsonObj = new JSONObject();
        String ok="";
        jsonObj.put("optType", 2);
        //加密的文件
        File file = new File(srcFile);
        int bigSize = adslGetBlockSize();
        if (file.length() > bigSize) {
            docAttach.put("bigFlag", true);
        }else{
            docAttach.put("bigFlag", false);
        }
        docAttach.put("FileName", file.getName());
        docAttach.put("Data", getFileData(file,bigSize));
        jsonObj.put("docAttach", docAttach);
        String slabelStr=sendPost(JAVA_URL+"/OptJavaFileSlab",jsonObj);
        JSONObject ret= JSONObject.parseObject(slabelStr);
        JSONObject docA= JSONObject.parseObject(ret.getString("slAttach"));
        if (ret.getInteger("ret") == 1) {
            ok=new String(Base64.decodeBase64(docA.getString("Data").getBytes()));
            //ok=new String(Base64.decodeBase64(docA.getString("Data").getBytes()),"UTF-8");//中文乱码时要抛异常
            System.out.println("文件密级信息读取成功："+ok);
            //writeFile(decFile, docA.getString("Data"));
            //ok="1";
        }else if(ret.getInteger("ret") == -3){
            ok="-3";
            System.out.println("文件为明文功："+ok);
        }else
            ok="0";
        return ok;
    }

    /**
     * 解密
     * @param srcFile 密文文件
     * @param decFile 解密成功后保存的文件
     * @return
     */

    public static String adslRemoveSlabel(String srcFile,String decFile){
        if(decFile.equals("")){
            decFile=srcFile;
        }
        JSONObject docAttach = new JSONObject();
        JSONObject jsonObj = new JSONObject();
        jsonObj.put("optType", 3);
        String ok="";
        //明文文件
        File file = new File(srcFile);
        int bigSize = adslGetBlockSize();
        if (file.length() > bigSize) {
            docAttach.put("bigFlag", true);
        }else{
            docAttach.put("bigFlag", false);
        }
        docAttach.put("FileName", file.getName());
        docAttach.put("Data", getFileData(file,bigSize));
        jsonObj.put("docAttach", docAttach);
        String slabelStr=sendPost(JAVA_URL+"/OptJavaFileSlab",jsonObj);
        JSONObject ret= JSONObject.parseObject(slabelStr);
        if (ret.getInteger("ret") == 1 ) {
            long totalS=ret.getLong("totalS");//获取操作文件后文件的大小
            JSONObject docA= JSONObject.parseObject(ret.getString("slAttach"));
            if(totalS>bigSize) {
                long readSize = 0;
                String FileName=docA.getString("FileName");
                JSONObject json = new JSONObject();
                while (readSize < totalS) {
                    json = new JSONObject();
                    json.put("FileName",FileName);
                    json.put("readSize", readSize);
                    String bigStr = sendPost(JAVA_URL + "/BigFileDown", json);
                    JSONObject bigret = JSONObject.parseObject(bigStr);
                    readSize = bigret.getLong("readSize");
                    writeFile(decFile, bigret.getString("Data"));
                }
                ok=file_get_contents(decFile);
                System.out.println("大文件解密成功");
            }else {
                // writeFile(decFile, docA.getString("Data"));
                ok=new String(Base64.decodeBase64(docA.getString("Data").getBytes()));
                //ok=new String(Base64.decodeBase64(docA.getString("Data").getBytes()),"UTF-8");//中文乱码时要抛异常
                System.out.println("文件解密成功");
            }
        }else
            ok="0";
        return ok;
    }

    /**
     * 修改密级文件的加密信息
     * @param srcFile 原密文文件
     * @param decFile 修改后保存的密级信息文件
     * @return
     */
    public static String adslAddSlabelEx(String srcFile,String decFile){
        if(decFile.equals("")){
            decFile=srcFile;
        }
        JSONObject docAttach = new JSONObject();
        JSONObject jsonObj = new JSONObject();
        jsonObj.put("optType", 4);
        String ok="0";
        //明文文件
        File file = new File(srcFile);
        //密级文件
        int bigSize = adslGetBlockSize();
        if (file.length() > bigSize) {
            docAttach.put("bigFlag", true);
        }else{
            docAttach.put("bigFlag", false);
        }
        docAttach.put("FileName", file.getName());
        docAttach.put("Data", getFileData(file,bigSize));
        String xmlString = XmlUtils.createSercetXml();//密级属性字符串
        jsonObj.put("slInfo",new String(Base64.encodeBase64(xmlString.getBytes())));//密级属性定义
        jsonObj.put("docAttach", docAttach);
        String slabelStr=sendPost(JAVA_URL+"/OptJavaFileSlab",jsonObj);
        JSONObject ret= JSONObject.parseObject(slabelStr);
        if (ret.getInteger("ret") == 1 ) {
            long totalS = ret.getLong("totalS");//获取操作文件后文件的大小
            JSONObject docA= JSONObject.parseObject(ret.getString("slAttach"));
            if (totalS > bigSize) {
                long readSize = 0;
                String FileName=docA.getString("FileName");
                JSONObject json = new JSONObject();
                while (readSize < totalS) {
                    json = new JSONObject();
                    json.put("FileName", FileName);
                    json.put("readSize", readSize);
                    String bigStr = sendPost(JAVA_URL + "/BigFileDown", json);
                    JSONObject bigret = JSONObject.parseObject(bigStr);
                    readSize = bigret.getLong("readSize");
                    writeFile(decFile, bigret.getString("Data"));
                }
                ok=file_get_contents(decFile);
                System.out.println("大文件修改密级成功");
            } else {
                //writeFile(decFile, docA.getString("Data"));
                ok=new String(Base64.decodeBase64(docA.getString("Data").getBytes()));
                //ok=new String(Base64.decodeBase64(docA.getString("Data").getBytes()),"UTF-8");//中文乱码时要抛异常
                System.out.println("文件修改密级成功");
            }
        }
        return ok;
    }

    /**
     * 文件流转
     * @param srcFile 源文件
     * @param type 转换方向：0 从内部格式转换外部格式 1 从外部格式转换为内部格式
     * @param uid 责任人UID（8字节）：从外部格式转换为内部格式时有效，从内部格式转换为外部格式时忽略
     * @param decFile 流转后保存的文件
     * @return
     */
    public static String adslConvertSlabel(String srcFile, int type, String uid,String decFile){
        if(decFile.equals("")){
            decFile=srcFile;
        }
        JSONObject docAttach = new JSONObject();
        JSONObject jsonObj = new JSONObject();
        jsonObj.put("optType", 5);
        String ok="";
        //源文件
        File file = new File(srcFile);
        int bigSize = adslGetBlockSize();
        if (file.length() > bigSize) {
            docAttach.put("bigFlag", true);
        }else{
            docAttach.put("bigFlag", false);
        }
        docAttach.put("FileName", file.getName());
        docAttach.put("Data", getFileData(file,bigSize));
        jsonObj.put("uid", uid);
        jsonObj.put("type", type);
        jsonObj.put("docAttach", docAttach);
        String slabelStr=sendPost(JAVA_URL+"/OptJavaFileSlab",jsonObj);
        JSONObject ret= JSONObject.parseObject(slabelStr);
        if (ret.getInteger("ret") == 1 ) {
            long totalS = ret.getLong("totalS");//获取操作文件后文件的大小
            JSONObject docA= JSONObject.parseObject(ret.getString("slAttach"));
            if (totalS > bigSize) {
                long readSize = 0;
                String FileName=docA.getString("FileName");
                JSONObject json = new JSONObject();
                while (readSize < totalS) {
                    json = new JSONObject();
                    json.put("FileName", FileName);
                    json.put("readSize", readSize);
                    String bigStr = sendPost(JAVA_URL+ "/BigFileDown", json);
                    JSONObject bigret = JSONObject.parseObject(bigStr);
                    readSize = bigret.getLong("readSize");
                    writeFile(decFile, bigret.getString("Data"));
                }
                ok=file_get_contents(decFile);
                System.out.println("大文件流转成功");
            } else {
                //writeFile(decFile, docA.getString("Data"));
                ok=new String(Base64.decodeBase64(docA.getString("Data").getBytes()));
                //ok=new String(Base64.decodeBase64(docA.getString("Data").getBytes()),"UTF-8");//中文乱码时要抛异常
                System.out.println("文件流转成功");
            }
        }else
            ok="0";
        return ok;
    }

    /**
     * 基于运管的流转
     * @param srcFile
     * @param type 转换方向：0 从内部格式转换外部格式 1 从外部格式转换为内部格式
     * @param uid
     * @param decFile
     * @return
     */
    public static String adslRemoveSlabel(String srcFile,int type,String uid,String decFile){
        if(decFile.equals("")){
            decFile=srcFile;
        }
        JSONObject docAttach = new JSONObject();
        JSONObject jsonObj = new JSONObject();
        jsonObj.put("optType", 6);
        String ok="";
        //源文件
        File file = new File(srcFile);
        int bigSize = adslGetBlockSize();
        if (file.length() > bigSize) {
            docAttach.put("bigFlag", true);
        }else{
            docAttach.put("bigFlag", false);
        }
        docAttach.put("FileName", file.getName());
        docAttach.put("Data", getFileData(file,bigSize));
        jsonObj.put("uid", uid);
        jsonObj.put("flag", type);
        jsonObj.put("docAttach", docAttach);
        String slabelStr=sendPost(JAVA_URL+"/OptJavaFileSlab",jsonObj);
        JSONObject ret= JSONObject.parseObject(slabelStr);
        if (ret.getInteger("ret") == 1 ) {
            long totalS = ret.getLong("totalS");//获取操作文件后文件的大小
            JSONObject docA= JSONObject.parseObject(ret.getString("slAttach"));
            if (totalS > bigSize) {
                long readSize = 0;
                String FileName=docA.getString("FileName");
                JSONObject json = new JSONObject();
                while (readSize < totalS) {
                    json = new JSONObject();
                    json.put("FileName",FileName);
                    json.put("readSize", readSize);
                    String bigStr = sendPost(JAVA_URL+ "/BigFileDown", json);
                    JSONObject bigret = JSONObject.parseObject(bigStr);
                    readSize = bigret.getLong("readSize");
                    writeFile(decFile, bigret.getString("Data"));
                }
                ok=file_get_contents(decFile);
            } else {
                //writeFile(decFile, docA.getString("Data"));
                ok=new String(Base64.decodeBase64(docA.getString("Data").getBytes()));
                //ok=new String(Base64.decodeBase64(docA.getString("Data").getBytes()),"UTF-8");//中文乱码时要抛异常
            }
        }else
            ok="0";
        return ok;
    }

    /**
     * 上传大文件
     *
     * @param file
     * @param blockSize
     * @return
     */
    private static String getFileData(File file, int blockSize) {
        logger.info("上传文件到客户端");
        long startTime = new Date().getTime();
        //判断是否大文件
        long totalSize = file.length();
        String fileData = "";
        // InputStream inputStream = null;
        FileInputStream inputStream = null;
        String fileName = file.getName();
        try {
            inputStream = new FileInputStream(file);
            //inputStream = file.getInputStream();
            if (totalSize <= blockSize) {
                byte[] fileByte = new byte[inputStream.available()];
                inputStream.read(fileByte);
                fileData = new String(Base64.encodeBase64(fileByte));
            } else {
                byte[] fileUpLoadByte = new byte[blockSize];
                int len;
                while ((len = inputStream.read(fileUpLoadByte)) != -1) {
                    byte[] databyte = new byte[len];
                    System.arraycopy(fileUpLoadByte, 0, databyte, 0, len);
                    String data_temp = new String(Base64.encodeBase64(databyte));
                    JSONObject paramObject = new JSONObject();
                    JSONObject tem_upLoadObject = new JSONObject();
                    tem_upLoadObject.put("FileName", fileName);
                    tem_upLoadObject.put("Data", data_temp);
                    sendPost(JAVA_URL+ "/BigFileUp", tem_upLoadObject);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        long endTime = new Date().getTime();
        logger.info("上传文件到本地用时：" + (endTime - startTime));
        return fileData;
    }

    //写入文件
    private static void writeFile(String fileName, String data) {
        FileOutputStream fos = null;
        try {
            File file = new File(fileName);
            if (!file.exists()) {
                file.createNewFile();
            }
            byte[] dataByte = Base64.decodeBase64(data.getBytes());
            fos = new FileOutputStream(file, true);
            fos.write(dataByte);
            fos.flush();
        } catch (Exception e) {
            logger.error(e.getMessage(), "写入文件失败");
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    private static String file_get_contents(String fileName) {
        String result = "";
        File file = new File(fileName);
        if (file.exists()) {
            try {
                FileInputStream fis = new FileInputStream(file);

                byte[] fileByte = new byte[fis.available()];
                fis.read(fileByte);
                //result = new BASE64Encoder().encode(fileByte);//返回字符串
                result =new String(Base64.encodeBase64(fileByte));
                fis.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }
}
